/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package casino;

import java.util.Set;

/**
 * A player that doubles his bet on every loss and resets his bet to a base amount
 * on each win. 
 * 
 * @author amaghfur
 * @since 1.0
 */
public class Martingale extends Player {
    
    /** times lost */
    private int lossCount = 0;
    /** the multiplier for the martingale strategy */
    protected int betMultiplier = 1;
    /** always bet on black */
    protected Outcome black;
    /** the very first bet amount */
    protected int firstBet = 10;
    
    /**
     * Concrete constructor for martingale.
     * 
     * @param tableToPlay       table this player plays on
     * @param startingStake     this player's starting stake
     */
    public Martingale(Table tableToPlay) {
        super(tableToPlay);
        black = OutcomeFactory.getOutcomeFactory().createOutcome("Black", 1);
    }
    
    /**
     * Getter for black.
     * 
     * @return  black outcome 
     */
    protected Outcome getBlack() {
        return black;
    }
    
    /**
     * Tells this player to place bets in martingale fashion i.e. double the previous bet
     * if lost.
     */
    @Override
    public void placeBets() {
        Rational betAmount = new Rational(firstBet*betMultiplier);
        if (betAmount.greaterThan(getStake())) { // end session if not enough money to follow betting strategy
            setRounds(0);
            return;
        }

        Bet blackBet = new Bet(betAmount, black);
        
        try {
            getTable().placeBet(blackBet);
            setStake(getStake().minus(betAmount));
        }
        catch (InvalidBetException e) {
            System.err.println("Caught InvalidBetException: " + e.getMessage());
        }  
    }
    
    /**
     * Notifies this player that his bet specified on the argument is a winner and
     * by how much.
     * 
     * @param bet   winning bet
     */
    @Override
    public void win(Bet bet) {
        setStake(getStake().plus(bet.winAmount()));
        reset();
        System.out.println(bet.toString() + " -> won " + bet.winAmount().toString());
    }
    
    /**
     * Notifies this player that his bet specified on the argument is a loser and
     * by how much.
     * 
     * @param bet   losing bet
     */
    @Override
    public void lose(Bet bet) {
        lossCount++;
        betMultiplier = (int)Math.pow(2, lossCount); 
        System.out.println(bet.toString() + " -> lost " + bet.loseAmount().toString());
    }

    /**
     * Inherited abstract method not important for this subclass.
     * 
     * @param outcomes 
     */
    @Override
    public void winners(Set<Outcome> outcomes) {
    }
    
    /**
     * Resets this player's state. Note that it does not reset to his original stake though.
     */
    @Override
    public void reset() {
        lossCount = 0;
        betMultiplier = 1;        
    }
}
